package bookstore.presentation;

import static java.lang.System.out;

import java.util.HashMap;
import java.util.Map;

import bookstore.domain.CODE;
import bookstore.domain.MSG;
import bookstore.util.In;

public class MenuImpl implements Menu {
	Map<Integer, String[]> menu;
	StringBuffer buffer;
	Shop shop;

	public MenuImpl() {
		this(null);
	}

	public MenuImpl(Shop shop) {
		menu = new HashMap<Integer, String[]>();
		buffer = new StringBuffer();
		this.shop = shop;
		setup();
	}

	// setup menu item.
	private void setup() {
		menu.clear();
		menu.put(CODE.SHOP_LOGIN, item("HOST", "GUEST"));
		menu.put(CODE.HOST, item("STOCK", "SALES"));
		menu.put(CODE.HOST_STOCK, item("LIST", "ADD", "MODIFY", "DEL"));
		menu.put(CODE.HOST_SELL, item("LIST", "DELIIVERY", "CANCEL"));
		menu.put(CODE.GUEST, item("SHOPPING", "CART"));
		menu.put(CODE.GUEST_BUY, item("LIST", "BUY"));
		menu.put(CODE.GUEST_CART, item("LIST", "REMOVE", "PAY"));
	}

	// translate menu item.
	private String[] item(String... item) {
		return item;
	}

	// choose menu number.
	private int choose(int code) {
		buffer.delete(0, buffer.capacity());
		String[] line = menu.get(code);
		for (int i = 0; i < line.length; i++) {
			buffer.append(i + 1);
			buffer.append(":");
			buffer.append(line[i]);
			buffer.append(", ");
		}
		buffer.append("0:EXIT\n>> ");

		boolean isOK = false;
		int choice = 0;
		do {
			out.print(buffer);
			choice = In.nextInt();
			if (choice < 0 || choice > line.length)
				out.println(MSG.FAIL + MSG.INVALID_MENU_NUM);
			else
				isOK = true;
		} while (!isOK);
		return choice;
	}

	// display menu.
	public int play() {
		int choice = 0;
		while ((choice = choose(CODE.SHOP_LOGIN)) != 0) {
			if (!login(++choice)) {
				out.println(MSG.FAIL + MSG.LOGIN_INFO_INVALID);
				break;
			}
			switch (choice) {
			case CODE.HOST:
				while ((choice = choose(CODE.HOST)) != 0) {
					switch (CODE.HOST * 100 + choice * 10) {
					case CODE.HOST_STOCK:
						while ((choice = choose(CODE.HOST_STOCK)) != 0) {
							switch (CODE.HOST_STOCK + choice) {
							case CODE.HOST_STOCK_LIST:
								call(CODE.HOST_STOCK_LIST);
								break;
							case CODE.HOST_STOCK_ADD:
								call(CODE.HOST_STOCK_ADD);
								break;
							case CODE.HOST_STOCK_MODIFY:
								call(CODE.HOST_STOCK_MODIFY);
								break;
							case CODE.HOST_STOCK_DEL:
								call(CODE.HOST_STOCK_DEL);
								break;
							}
						}
						break;
					case CODE.HOST_SELL:
						while ((choice = choose(CODE.HOST_SELL)) != 0) {
							switch (CODE.HOST_SELL + choice) {
							case CODE.HOST_SELL_LIST:
								call(CODE.HOST_SELL_LIST);
								break;
							case CODE.HOST_SELL_SEND:
								call(CODE.HOST_SELL_SEND);
								break;
							case CODE.HOST_SELL_CANCEL:
								call(CODE.HOST_SELL_CANCEL);
								break;
							}
						}
						break;
					}
				}
				break;
			case CODE.GUEST:
				while ((choice = choose(CODE.GUEST)) != 0) {
					switch (CODE.GUEST * 100 + choice * 10) {
					case CODE.GUEST_BUY:
						while ((choice = choose(CODE.GUEST_BUY)) != 0) {
							switch (CODE.GUEST_BUY + choice) {
							case CODE.GUEST_BUY_LIST:
								call(CODE.GUEST_BUY_LIST);
								break;
							case CODE.GUEST_BUY_BUY:
								call(CODE.GUEST_BUY_BUY);
								break;
							}
						}
						break;
					case CODE.GUEST_CART:
						while ((choice = choose(CODE.GUEST_CART)) != 0) {
							switch (CODE.GUEST_CART + choice) {
							case CODE.GUEST_CART_LIST:
								call(CODE.GUEST_CART_LIST);
								break;
							case CODE.GUEST_CART_DEL:
								call(CODE.GUEST_CART_DEL);
								break;
							case CODE.GUEST_CART_PAY:
								call(CODE.GUEST_CART_PAY);
								break;
							}
						}
						break;
					}
				}
				break;
			}
		}
		return choice;
	}

	// call method.
	private void call(int code) {
		shop.call(code);
	}

	// call login method.
	private boolean login(int who) {
		return shop.login(who);
	}
}
